﻿using System;
using System.Xml;

namespace NuGet.Enterprise.Server.Xml
{
    /// <summary>
    /// Represents a base class for custom <see cref="XmlReader"/>.
    /// </summary>
    public abstract class XmlWrappingReader
       : XmlReader, IXmlLineInfo
    {
        #region Fields (1)

        XmlReader _baseReader;

        #endregion Fields

        #region Constructors (1)

        /// <summary>
        /// Initializes a new instance of the <see cref="XmlWrappingReader"/>.
        /// </summary>
        /// <param name="baseReader">The underlying reader this instance will wrap.</param>
        protected XmlWrappingReader(XmlReader baseReader)
        {
            if (baseReader == null)
            {
                throw new ArgumentNullException("baseReader");
            }

            _baseReader = baseReader;
        }

        #endregion Constructors

        #region Methods (17)

        /// <summary>
        /// See <see cref="XmlReader.Close"/>.
        /// </summary>
        public override void Close() { _baseReader.Close(); }

        /// <summary>
        /// See <see cref="XmlReader.Dispose"/>.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (ReadState != ReadState.Closed)
            {
                Close();
            }

            ((IDisposable)_baseReader).Dispose();
        }

        /// <summary>
        /// See <see cref="XmlReader.GetAttribute(int)"/>.
        /// </summary>
        public override string GetAttribute(int i) { return _baseReader.GetAttribute(i); }

        /// <summary>
        /// See <see cref="XmlReader.GetAttribute(string)"/>.
        /// </summary>
        public override string GetAttribute(string name) { return _baseReader.GetAttribute(name); }

        /// <summary>
        /// See <see cref="XmlReader.GetAttribute(string, string)"/>.
        /// </summary>
        public override string GetAttribute(string name, string namespaceURI) { { return _baseReader.GetAttribute(name, namespaceURI); } }

        /// <summary>
        /// See <see cref="IXmlLineInfo.HasLineInfo"/>.
        /// </summary>
        public bool HasLineInfo()
        {
            IXmlLineInfo info = _baseReader as IXmlLineInfo;
            if (info != null)
            {
                return info.HasLineInfo();
            }

            return false;
        }

        /// <summary>
        /// See <see cref="XmlReader.LookupNamespace"/>.
        /// </summary>
        public override string LookupNamespace(string prefix) { return _baseReader.LookupNamespace(prefix); }

        /// <summary>
        /// See <see cref="XmlReader.MoveToAttribute(int)"/>.
        /// </summary>
        public override void MoveToAttribute(int i) { _baseReader.MoveToAttribute(i); }

        /// <summary>
        /// See <see cref="XmlReader.MoveToAttribute(string)"/>.
        /// </summary>
        public override bool MoveToAttribute(string name) { return _baseReader.MoveToAttribute(name); }

        /// <summary>
        /// See <see cref="XmlReader.MoveToAttribute(string, string)"/>.
        /// </summary>
        public override bool MoveToAttribute(string name, string ns) { return _baseReader.MoveToAttribute(name, ns); }

        /// <summary>
        /// See <see cref="XmlReader.MoveToElement"/>.
        /// </summary>
        public override bool MoveToElement() { return _baseReader.MoveToElement(); }

        /// <summary>
        /// See <see cref="XmlReader.MoveToFirstAttribute"/>.
        /// </summary>
        public override bool MoveToFirstAttribute() { return _baseReader.MoveToFirstAttribute(); }

        /// <summary>
        /// See <see cref="XmlReader.MoveToNextAttribute"/>.
        /// </summary>
        public override bool MoveToNextAttribute() { return _baseReader.MoveToNextAttribute(); }

        /// <summary>
        /// See <see cref="XmlReader.Read"/>.
        /// </summary>
        public override bool Read() { return _baseReader.Read(); }

        /// <summary>
        /// See <see cref="XmlReader.ReadAttributeValue"/>.
        /// </summary>
        public override bool ReadAttributeValue() { return _baseReader.ReadAttributeValue(); }

        /// <summary>
        /// See <see cref="XmlReader.ReadValueChunk"/>.
        /// </summary>
        public override int ReadValueChunk(char[] buffer, int index, int count) { return _baseReader.ReadValueChunk(buffer, index, count); }

        /// <summary>
        /// See <see cref="XmlReader.ResolveEntity"/>.
        /// </summary>
        public override void ResolveEntity() { _baseReader.ResolveEntity(); }

        #endregion Methods

        #region Properties (27)

        /// <summary>
        /// See <see cref="XmlReader.AttributeCount"/>.
        /// </summary>
        public override int AttributeCount { get { return _baseReader.AttributeCount; } }

        /// <summary>
        /// Gets or sets the underlying reader this instance is wrapping.
        /// </summary>
        protected XmlReader BaseReader
        {
            get { return _baseReader; }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }

                _baseReader = value;
            }
        }

        /// <summary>
        /// See <see cref="XmlReader.BaseURI"/>.
        /// </summary>
        public override string BaseURI { get { return _baseReader.BaseURI; } }

        /// <summary>
        /// See <see cref="XmlReader.CanReadBinaryContent"/>.
        /// </summary>
        public override bool CanReadBinaryContent { get { return _baseReader.CanReadBinaryContent; } }

        /// <summary>
        /// See <see cref="XmlReader.CanReadValueChunk"/>.
        /// </summary>
        public override bool CanReadValueChunk { get { return _baseReader.CanReadValueChunk; } }

        /// <summary>
        /// See <see cref="XmlReader.CanResolveEntity"/>.
        /// </summary>
        public override bool CanResolveEntity { get { return _baseReader.CanResolveEntity; } }

        /// <summary>
        /// See <see cref="XmlReader.Depth"/>.
        /// </summary>
        public override int Depth { get { return _baseReader.Depth; } }

        /// <summary>
        /// See <see cref="XmlReader.EOF"/>.
        /// </summary>
        public override bool EOF { get { return _baseReader.EOF; } }

        /// <summary>
        /// See <see cref="XmlReader.HasValue"/>.
        /// </summary>
        public override bool HasValue { get { return _baseReader.HasValue; } }

        /// <summary>
        /// See <see cref="XmlReader.IsDefault"/>.
        /// </summary>
        public override bool IsDefault { get { return _baseReader.IsDefault; } }

        /// <summary>
        /// See <see cref="XmlReader.IsEmptyElement"/>.
        /// </summary>
        public override bool IsEmptyElement { get { return _baseReader.IsEmptyElement; } }

        /// <summary>
        /// See <see cref="IXmlLineInfo.LineNumber"/>.
        /// </summary>
        public int LineNumber
        {
            get
            {
                IXmlLineInfo info = _baseReader as IXmlLineInfo;
                if (info != null)
                {
                    return info.LineNumber;
                }

                return 0;
            }
        }

        /// <summary>
        /// See <see cref="IXmlLineInfo.LinePosition"/>.
        /// </summary>
        public int LinePosition
        {
            get
            {
                IXmlLineInfo info = _baseReader as IXmlLineInfo;

                if (info != null)
                {
                    return info.LinePosition;
                }

                return 0;
            }
        }

        /// <summary>
        /// See <see cref="XmlReader.LocalName"/>.
        /// </summary>
        public override string LocalName { get { return _baseReader.LocalName; } }

        /// <summary>
        /// See <see cref="XmlReader.Name"/>.
        /// </summary>
        public override string Name { get { return _baseReader.Name; } }

        /// <summary>
        /// See <see cref="XmlReader.NamespaceURI"/>.
        /// </summary>
        public override string NamespaceURI { get { return _baseReader.NamespaceURI; } }

        /// <summary>
        /// See <see cref="XmlReader.NameTable"/>.
        /// </summary>
        public override XmlNameTable NameTable { get { return _baseReader.NameTable; } }

        /// <summary>
        /// See <see cref="XmlReader.NodeType"/>.
        /// </summary>
        public override XmlNodeType NodeType { get { return _baseReader.NodeType; } }

        /// <summary>
        /// See <see cref="XmlReader.Prefix"/>.
        /// </summary>
        public override string Prefix { get { return _baseReader.Prefix; } }

        /// <summary>
        /// See <see cref="XmlReader.QuoteChar"/>.
        /// </summary>
        public override char QuoteChar { get { return _baseReader.QuoteChar; } }

        /// <summary>
        /// See <see cref="XmlReader.ReadState"/>.
        /// </summary>
        public override ReadState ReadState { get { return _baseReader.ReadState; } }

        /// <summary>
        /// See <see cref="XmlReader.this[int]"/>.
        /// </summary>
        public override string this[int i] { get { return _baseReader[i]; } }

        /// <summary>
        /// See <see cref="XmlReader.this[string]"/>.
        /// </summary>
        public override string this[string name] { get { return _baseReader[name]; } }

        /// <summary>
        /// See <see cref="XmlReader.this[string, string]"/>.
        /// </summary>
        public override string this[string name, string namespaceURI] { get { return _baseReader[name, namespaceURI]; } }

        /// <summary>
        /// See <see cref="XmlReader.Value"/>.
        /// </summary>
        public override string Value { get { return _baseReader.Value; } }

        /// <summary>
        /// See <see cref="XmlReader.XmlLang"/>.
        /// </summary>
        public override string XmlLang { get { return _baseReader.XmlLang; } }

        /// <summary>
        /// See <see cref="XmlReader.XmlSpace"/>.
        /// </summary>
        public override XmlSpace XmlSpace { get { return _baseReader.XmlSpace; } }

        #endregion Properties
    }
}
